From a2be8eba3aaf11a9a73092793d27d6d46b4270cd Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 19 Jun 2021 09:18:26 +0200 Subject: Add .so target. Fix ready state checks. --- Makefile | 2 +- Makefile.dg | 4 +- cppbuild.cc | 77 ++++++++++++++-------- libcppbuild.cc | 76 ++++++++++++++++++---- task.cc | 16 +++-- task.h | 13 +++- task_cc.cc | 7 ++ task_ld.cc | 11 +++- task_so.cc | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ task_so.h | 42 ++++++++++++ 10 files changed, 397 insertions(+), 49 deletions(-) create mode 100644 task_so.cc create mode 100644 task_so.h diff --git a/Makefile b/Makefile index 335e5aa..af29818 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ SRC = \ OBJ = $(patsubst %.cc,%.o,$(SRC)) -CXXFLAGS = -s -O3 -std=c++17 +CXXFLAGS = -g -O3 -std=c++17 -I. %.o: %.cc g++ $(CXXFLAGS) -c $< -o $@ diff --git a/Makefile.dg b/Makefile.dg index 548c0cb..9d8cf09 100644 --- a/Makefile.dg +++ b/Makefile.dg @@ -111,8 +111,8 @@ SRC = \ OBJ = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(patsubst %.cpp,%.o,$(SRC)))) -CXXFLAGS = -DUI_X11 -g -Wall -Werror -std=c++11 -Idrumgizmo/getoptpp -Idrumgizmo/ -Idrumgizmo/hugin -Idrumgizmo/plugingui/ -Idrumgizmo/src/ -Idrumgizmo/zita-resampler/libs -Idrumgizmo/pugixml/src -CFLAGS = -g -Wall -Werror +CXXFLAGS = -DUI_X11 -O3 -g -Wall -Werror -std=c++11 -Idrumgizmo/getoptpp -Idrumgizmo/ -Idrumgizmo/hugin -Idrumgizmo/plugingui/ -Idrumgizmo/src/ -Idrumgizmo/zita-resampler/libs -Idrumgizmo/pugixml/src +CFLAGS = -O3 -g -Wall -Werror LDFLAGS = -lm -lX11 -lXext -pthread -lsndfile %.o: %.c diff --git a/cppbuild.cc b/cppbuild.cc index 737ba83..882fe63 100644 --- a/cppbuild.cc +++ b/cppbuild.cc @@ -24,6 +24,49 @@ std::vector configs() { { .target = "plugingui", + .sources = { + "drumgizmo/zita-resampler/libs/cresampler.cc", + "drumgizmo/zita-resampler/libs/resampler-table.cc", + "drumgizmo/zita-resampler/libs/resampler.cc", + "drumgizmo/zita-resampler/libs/vresampler.cc", + "drumgizmo/hugin/hugin.c", + "drumgizmo/pugixml/src/pugixml.cpp", + }, + .depends = { + "libplugingui.so", + }, + .cxxflags = { + "-DUI_X11", + "-O3", + "-g", + "-Wall", + "-Werror", + "-std=c++11", + "-Idrumgizmo/getoptpp", + "-Idrumgizmo/", + "-Idrumgizmo/hugin", + "-Idrumgizmo/plugingui/", + "-Idrumgizmo/src/", + "-Idrumgizmo/zita-resampler/libs", + "-Idrumgizmo/pugixml/src", + }, + .cflags = { + "-g", + //"-O3", + "-Wall", + "-Werror", + }, + .ldflags = { + "-lm", + "-lX11", + "-lXext", + "-lsndfile", + "-pthread", + } + }, + + { + .target = "src.a", .sources = { "drumgizmo/src/audiocache.cc", "drumgizmo/src/audiocacheeventhandler.cc", @@ -66,18 +109,10 @@ std::vector configs() "drumgizmo/src/velocityfilter.cc", "drumgizmo/src/versionstr.cc", "drumgizmo/src/zrwrapper.cc", - "drumgizmo/zita-resampler/libs/cresampler.cc", - "drumgizmo/zita-resampler/libs/resampler-table.cc", - "drumgizmo/zita-resampler/libs/resampler.cc", - "drumgizmo/zita-resampler/libs/vresampler.cc", - "drumgizmo/hugin/hugin.c", - "drumgizmo/pugixml/src/pugixml.cpp", - "drumgizmo/plugingui/lodepng/lodepng.cpp", - }, - .depends = { - "plugingui.a", }, + .depends = {}, .cxxflags = { + "-fPIC", "-DUI_X11", "-O3", "-g", @@ -92,23 +127,12 @@ std::vector configs() "-Idrumgizmo/zita-resampler/libs", "-Idrumgizmo/pugixml/src", }, - .cflags = { - "-g", - //"-O3", - "-Wall", - "-Werror", - }, - .ldflags = { - "-lm", - "-lX11", - "-lXext", - "-lsndfile", - "-pthread", - } + .cflags = {}, + .ldflags = {} }, { - .target = "plugingui.a", + .target = "libplugingui.so", .sources = { "drumgizmo/plugingui/abouttab.cc", "drumgizmo/plugingui/bleedcontrolframecontent.cc", @@ -171,8 +195,11 @@ std::vector configs() "drumgizmo/plugingui/voicelimitframecontent.cc", "drumgizmo/plugingui/widget.cc", "drumgizmo/plugingui/window.cc", + "drumgizmo/plugingui/lodepng/lodepng.cpp", + }, + .depends = { + "src.a", }, - .depends = {}, .cxxflags = { "-DUI_X11", "-O3", diff --git a/libcppbuild.cc b/libcppbuild.cc index 7f0a355..69d23ba 100644 --- a/libcppbuild.cc +++ b/libcppbuild.cc @@ -10,10 +10,13 @@ #include #include +#include + #include "libcppbuild.h" #include "task_cc.h" #include "task_ld.h" #include "task_ar.h" +#include "task_so.h" #include "settings.h" #include @@ -23,6 +26,8 @@ using namespace std::chrono_literals; std::list> taskFactory(const BuildConfiguration& config, const Settings& settings) { + std::filesystem::path targetFile(config.target); + std::vector objects; std::list> tasks; for(const auto& file : config.sources) @@ -31,19 +36,28 @@ std::list> taskFactory(const BuildConfiguration& config, objects.push_back(tasks.back()->target()); } - std::filesystem::path targetFile(config.target); if(targetFile.extension() == ".a") { // static lib tasks.emplace_back(std::make_shared(config, settings, config.target, objects)); } + else if(targetFile.extension() == ".so") + { + if(targetFile.stem().string().substr(0, 3) != "lib") + { + std::cerr << "Dynamic library target must have 'lib' prefix\n"; + exit(1); + } + // dynamic lib + tasks.emplace_back(std::make_shared(config, settings, config.target, + objects)); + } else { - // binary + // executable tasks.emplace_back(std::make_shared(config, settings, config.target, objects)); - } return tasks; @@ -68,10 +82,9 @@ std::shared_ptr getNextTask(const std::list>& allTas return nullptr; } -int main(int argc, const char* argv[]) +int main(int argc, char* argv[]) { Settings settings; - // TODO: Set from commandline settings.builddir = "build/foo"; @@ -80,6 +93,40 @@ int main(int argc, const char* argv[]) settings.verbose = 0; + dg::Options opt; + + opt.add("jobs", required_argument, 'j', + "Number of parallel jobs.", + [&]() { + try + { + settings.parallel_processes = std::stoi(optarg); + } + catch(...) + { + std::cerr << "Not a number\n"; + return 1; + } + return 0; + }); + + opt.add("verbose", no_argument, 'v', + "Be verbose.", + [&]() { + settings.verbose++; + return 0; + }); + + opt.add("help", no_argument, 'h', + "Print this help text.", + [&]() { + std::cout << "usage stuff\n"; + opt.help(); + return 0; + }); + + opt.process(argc, argv); + std::filesystem::path builddir(settings.builddir); std::filesystem::create_directories(builddir); @@ -106,19 +153,22 @@ int main(int argc, const char* argv[]) } } - if(argc == 2 && std::string(argv[1]) == "clean") + for(auto const &arg : opt.arguments()) { - std::cout << "Cleaning\n"; - //std::filesystem::remove_all(builddir); - for(auto& task : tasks) + if(arg == "clean") { - if(task->clean() != 0) + std::cout << "Cleaning\n"; + //std::filesystem::remove_all(builddir); + for(auto& task : tasks) { - return 1; + if(task->clean() != 0) + { + return 1; + } } - } - return 0; + return 0; + } } std::cout << "Building\n"; diff --git a/task.cc b/task.cc index d539b50..10e9368 100644 --- a/task.cc +++ b/task.cc @@ -39,32 +39,38 @@ bool Task::ready() { for(const auto& task : dependsTasks) { - if(task->dirty() && !task->done()) + if(task->dirty() || task->state() == State::Running) { return false; } } + task_state.store(State::Ready); return true; } int Task::run() { - if(is_done.load()) + if(task_state.load() == State::Done) { return 0; } + task_state.store(State::Running); auto ret = runInner(); if(ret == 0) { - is_done.store(true); + task_state.store(State::Done); + } + else + { + task_state.store(State::Error); } return ret; } -bool Task::done() const +State Task::state() const { - return is_done.load(); + return task_state.load(); } diff --git a/task.h b/task.h index 2dd05e3..00b01d2 100644 --- a/task.h +++ b/task.h @@ -7,6 +7,15 @@ #include #include +enum class State +{ + Unknown, + Ready, + Running, + Done, + Error, +}; + class Task { public: @@ -17,13 +26,13 @@ public: bool dirty(); bool ready(); int run(); - bool done() const; + State state() const; virtual int clean() = 0 ; virtual std::vector depends() const = 0; virtual std::string target() const = 0; protected: - std::atomic is_done{false}; + std::atomic task_state{State::Unknown}; virtual int runInner() { return 0; }; virtual bool dirtyInner() { return false; } diff --git a/task_cc.cc b/task_cc.cc index 74654aa..4340f7b 100644 --- a/task_cc.cc +++ b/task_cc.cc @@ -178,6 +178,13 @@ int TaskCC::runInner() std::vector args; args.push_back("-MMD"); + + if(std::filesystem::path(config.target).extension() == ".so") + { + // Add -fPIC arg to all contained object files + args.push_back("-fPIC"); + } + args.push_back("-c"); args.push_back(std::string(sourceFile)); args.push_back("-o"); diff --git a/task_ld.cc b/task_ld.cc index fcde6d4..db0f955 100644 --- a/task_ld.cc +++ b/task_ld.cc @@ -117,7 +117,16 @@ int TaskLD::runInner() for(const auto& depFile : depFiles) { - args.push_back(depFile.string()); + if(depFile.extension() == ".so") + { + args.push_back(std::string("-L") + settings.builddir); + auto lib = depFile.stem().string().substr(3); // strip 'lib' prefix + args.push_back(std::string("-l") + lib); + } + else if(depFile.extension() == ".a") + { + args.push_back(depFile.string()); + } } for(const auto& flag : config.ldflags) diff --git a/task_so.cc b/task_so.cc new file mode 100644 index 0000000..afe5c32 --- /dev/null +++ b/task_so.cc @@ -0,0 +1,198 @@ +#include "task_so.h" + +#include +#include + +#include "libcppbuild.h" +#include "settings.h" +#include "execute.h" + +namespace +{ +std::string readFile(const std::string &fileName) +{ + std::ifstream ifs(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + + std::ifstream::pos_type fileSize = ifs.tellg(); + ifs.seekg(0, std::ios::beg); + + std::vector bytes(fileSize); + ifs.read(bytes.data(), fileSize); + + return std::string(bytes.data(), fileSize); +} + +std::vector addPrefix(const std::vector& lst, + const Settings& settings) +{ + std::vector out; + for(const auto& item : lst) + { + std::filesystem::path file = settings.builddir; + file /= item; + out.push_back(file.string()); + } + return out; +} +} // namespace :: + +TaskSO::TaskSO(const BuildConfiguration& config, + const Settings& settings, + const std::string& target, + const std::vector& objects) + : Task(addPrefix(config.depends, settings)) + , config(config) + , settings(settings) +{ + targetFile = settings.builddir; + targetFile /= target; + for(const auto& object : objects) + { + std::filesystem::path objectFile = object; + objectFiles.push_back(objectFile); + dependsStr.push_back(objectFile); + } + + for(const auto& dep : config.depends) + { + std::filesystem::path depFile = settings.builddir; + depFile /= dep; + depFiles.push_back(depFile); + } + + flagsFile = settings.builddir / targetFile.stem(); + flagsFile += ".flags"; +} + +bool TaskSO::dirtyInner() +{ + if(!std::filesystem::exists(targetFile)) + { + return true; + } + + if(!std::filesystem::exists(flagsFile)) + { + return true; + } + + for(const auto& objectFile : objectFiles) + { + if(std::filesystem::last_write_time(targetFile) <= + std::filesystem::last_write_time(objectFile)) + { + return true; + } + } + + { + auto lastFlags = readFile(flagsFile); + if(flagsString() != lastFlags) + { + //std::cout << "The compiler flags changed\n"; + return true; + } + } + + return false; +} + +int TaskSO::runInner() +{ + std::string objectlist; + for(const auto& objectFile : objectFiles) + { + if(!objectlist.empty()) + { + objectlist += " "; + } + objectlist += std::string(objectFile); + } + + std::vector args; + + args.push_back("-fPIC"); + args.push_back("-shared"); + + args.push_back("-o"); + args.push_back(std::string(targetFile)); + + for(const auto& objectFile : objectFiles) + { + args.push_back(std::string(objectFile)); + } + + for(const auto& depFile : depFiles) + { + args.push_back(depFile.string()); + } + + for(const auto& flag : config.ldflags) + { + args.push_back(flag); + } + + { // Write flags to file. + std::ofstream flagsStream(flagsFile); + flagsStream << flagsString(); + } + + if(settings.verbose == 0) + { + std::cout << "LD => " << targetFile.string() << "\n"; + } + + return execute("/usr/bin/g++", args, settings.verbose > 0); +} + +int TaskSO::clean() +{ + if(std::filesystem::exists(targetFile)) + { + std::cout << "Removing " << std::string(targetFile) << "\n"; + std::filesystem::remove(targetFile); + } + + if(std::filesystem::exists(flagsFile)) + { + std::cout << "Removing " << std::string(flagsFile) << "\n"; + std::filesystem::remove(flagsFile); + } + + return 0; +} + +std::vector TaskSO::depends() const +{ + std::vector deps; + for(const auto& objectFile : objectFiles) + { + deps.push_back(objectFile.string()); + } + + for(const auto& depFile : depFiles) + { + deps.push_back(depFile.string()); + } + + return deps; +} + +std::string TaskSO::target() const +{ + return std::string(targetFile); +} + +std::string TaskSO::flagsString() const +{ + std::string flagsStr; + for(const auto& flag : config.ldflags) + { + if(!flagsStr.empty()) + { + flagsStr += " "; + } + flagsStr += flag; + } + return flagsStr; +} diff --git a/task_so.h b/task_so.h new file mode 100644 index 0000000..864d108 --- /dev/null +++ b/task_so.h @@ -0,0 +1,42 @@ +// -*- c++ -*- +#pragma once + +#include "task.h" + +#include +#include +#include +#include + +struct BuildConfiguration; +struct Settings; + +class TaskSO + : public Task +{ +public: + TaskSO(const BuildConfiguration& config, + const Settings& settings, + const std::string& target, + const std::vector& objects); + + bool dirtyInner() override; + + int runInner() override; + int clean() override; + + std::vector depends() const override; + + std::string target() const override; + +private: + std::string flagsString() const; + + std::vector objectFiles; + std::vector depFiles; + std::filesystem::path targetFile; + std::filesystem::path flagsFile; + + const BuildConfiguration& config; + const Settings& settings; +}; -- cgit v1.2.3