www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Build Script in D

reply David <d dav1d.de> writes:
I wrote a build script, mainly for my own project, the last days I
rewrote it be as flexible as possible (It makes make obsolete, at least
in my case):

https://github.com/Dav1dde/BraLa/blob/master/build_brala.d

usage:
rdmd build_brala.d # you can rename it of course!
-j --jobs # like -j for makefiles
-c --cache # path to a cache file, default is .build_cache
--no-cache # disables the build cache
-o --override-cache # doesn't load the cache file, but writes the newer
version

How to actually use the fancy classes:
https://github.com/Dav1dde/BraLa/blob/master/build_brala.d#L303

The Builder class takes 4 arguments, the cache (MD5Cache and NoCache are
implemented), the linker (only dmd implemented), the D-compiler (only
dmd implemented) and the C-Compiler (gcc and dmc implemented)

The rest should get clear when reading main()

TODO:
 * documentation
 * other compilers (only a few lines for each compiler + a few to
implement Linker functionality)
 * provide helpers for the taskpool (maybe)
 * add logging options, currently every command is printed to stdout

Any input welcome!
Jan 10 2013
next sibling parent reply "Manipulator" <volcz kth.se> writes:
A class like this in Phobos would make it a lot easier for
newcomers. :-)
Jan 11 2013
parent reply "evilrat" <evilrat666 gmail.com> writes:
On Friday, 11 January 2013 at 08:36:11 UTC, Manipulator wrote:
 A class like this in Phobos would make it a lot easier for
 newcomers. :-)
maybe, but that version is a bit... cryptic. i think it should be ultra easy to use, but this script is more like python scons(yeah, maybe i'm too stupid to use it properly) i would love to see something like this: import std.builder; void main(string[] argv) { /* get builder with only home path where to build stuff. assuming compiler to be the same as current compiler and the same target(32 bit or 64 bit, release or debug) also something like this for custom target: auto builder = Builder( homepath!"./", arch!"x86", mode!"debug" ) pseudo signature: _struct_ Builder(vararg ...) */ auto builder = Builder( homepath("path_to_debug_location", "path_to_release")() )() // assuming all methods returns ref to self so it could be just simple calls builder.addSrcPath("path_to_src_folder_1"); // or can be chained builder.addSrcPath("path_to_src_folder_2"). addSrcPath("path_to_src_folder3"); builder.addImportPath("path_to_imports"); builder.addLinkLib("somelib.a"); // etc... // compiler log string log = builder.build(); // target path, i.e. "/users/me/coolstuff/bin/prog1" string productpath = builder.product(); writefln( "%s build %s", productpath, builder.success? "complete" : "failed!" ); ... } also to all above it would be good if there be some concept of multiple targets or jobs and ordering, to allow build stuff dependent on other stuff in one run
Jan 11 2013
parent reply David <d dav1d.de> writes:
 also something like this for custom target:
 auto builder = Builder( homepath!"./", arch!"x86", mode!"debug" )
Doesn't work, these are compiler flags, which differ from compiler to compiler. You could make the builder call the compiler to set the flag, but I would move that directly to the compiler.
 // assuming all methods returns ref to self so it could be just simple
 calls
 builder.addSrcPath("path_to_src_folder_1");
 // or can be chained
 builder.addSrcPath("path_to_src_folder_2").
   addSrcPath("path_to_src_folder3");
And how does chaining help? That makes everything just uglier.
 builder.addImportPath("path_to_imports");
 builder.addLinkLib("somelib.a");
Need to be set for the compiler, A C compiler doesn't need the flags of a D compiler
 // compiler log
 string log = builder.build();
The log should be in realtime to see where compilation takes longest etc.
 also to all above it would be good if there be some concept of multiple
 targets or jobs and ordering, to allow build stuff dependent on other
 stuff in one run
Everything is compiled without beeing linked, order doesn't mean anything, because everything will be linked together.
Jan 11 2013
parent reply "evilrat" <evilrat666 gmail.com> writes:
On Friday, 11 January 2013 at 14:01:48 UTC, David wrote:
 also something like this for custom target:
 auto builder = Builder( homepath!"./", arch!"x86", 
 mode!"debug" )
Doesn't work, these are compiler flags, which differ from compiler to compiler. You could make the builder call the compiler to set the flag, but I would move that directly to the compiler.
 // assuming all methods returns ref to self so it could be 
 just simple
 calls
 builder.addSrcPath("path_to_src_folder_1");
 // or can be chained
 builder.addSrcPath("path_to_src_folder_2").
   addSrcPath("path_to_src_folder3");
And how does chaining help? That makes everything just uglier.
 builder.addImportPath("path_to_imports");
 builder.addLinkLib("somelib.a");
Need to be set for the compiler, A C compiler doesn't need the flags of a D compiler
 // compiler log
 string log = builder.build();
The log should be in realtime to see where compilation takes longest etc.
 also to all above it would be good if there be some concept of 
 multiple
 targets or jobs and ordering, to allow build stuff dependent 
 on other
 stuff in one run
Everything is compiled without beeing linked, order doesn't mean anything, because everything will be linked together.
well the topic says script in D, so i assume this is for D and not C(there is already cmake, make and so on), and this is possible to get compiler info in D ugly chaining is not so ugly, and is just an option, there is anyway "with (...)" construct in D log is was an example and not requirement, i just say that such class when used with CTFE somehow would be helpful to do easy compile with all dependencies, i.e. you only compile one target and using CTFE it compiles other, possibly messy stuff but maybe anyone need this... anyway that's just a wishlist, not a must have list =3
Jan 11 2013
parent reply David <d dav1d.de> writes:
 well the topic says script in D, so i assume this is for D and not
 C(there is already cmake, make and so on), and this is possible to get
 compiler info in D
What if you need e.g. stb_image, one of the most awesome image-loading libraries in C?
 ugly chaining is not so ugly, and is just an option, there is anyway
 "with (...)" construct in D
I think it gets unreadable
 log is was an example and not requirement, i just say that such class
 when used with CTFE somehow would be helpful to do easy compile with all
 dependencies, i.e. you only compile one target and using CTFE it
 compiles other, possibly messy stuff but maybe anyone need this...
Why used in CTFE? I don't understand what you mean.
Jan 11 2013
parent reply "evilrat" <evilrat666 gmail.com> writes:
On Friday, 11 January 2013 at 18:14:01 UTC, David wrote:
 What if you need e.g. stb_image, one of  the most awesome 
 image-loading
 libraries in C?
for anything outside D there is enough makefiles, autotools, cmake, whatever. also there is OS package system which for sure contaion most of these libraries, for me it's enough to not bother about building own C build system
Jan 11 2013
parent reply David <d dav1d.de> writes:
 for anything outside D there is enough makefiles, autotools, cmake,
 whatever.
 also there is OS package system which for sure contaion most of these
 libraries, for me it's enough to not bother about building own C build
 system
Using make with D works great, also there is cmake for D. But try to use two tools (d buildscript and let's say cmake) on windows. You have to force the user to either install mingw/cygwin or cmake/make and VS (cmake can only generate for mingw-make and VS not dmc). Users will end up not using it. stb_image e.g. is in no "OS-Package" (which also don't exist for windows)
Jan 12 2013
parent reply "evilrat" <evilrat666 gmail.com> writes:
On Saturday, 12 January 2013 at 16:34:12 UTC, David wrote:
 Using make with D works great, also there is cmake for D. But 
 try to use
 two tools (d buildscript and let's say cmake) on windows. You 
 have to
 force the user to either install mingw/cygwin or cmake/make and 
 VS
 (cmake can only generate for mingw-make and VS not dmc). Users 
 will end
 up not using it.

 stb_image e.g. is in no "OS-Package" (which also don't exist 
 for windows)
of course makefiles work, it's just hated by so many programmers... for windows there is 99% chance that already compiled executables/libraries exists. and if some project doesn't have binaries for windows, it's maintainers fault, not windows. just imagine yourself compiling for example Qt or chrome on single core 2Ghz machine with 1gb ram because there is no compiled binaries, would you be happy after that? but... we already going to OT, i don't want to start holy wars about build systems.
Jan 12 2013
parent reply David <d dav1d.de> writes:
Am 13.01.2013 04:17, schrieb evilrat:
 On Saturday, 12 January 2013 at 16:34:12 UTC, David wrote:
 Using make with D works great, also there is cmake for D. But try to use
 two tools (d buildscript and let's say cmake) on windows. You have to
 force the user to either install mingw/cygwin or cmake/make and VS
 (cmake can only generate for mingw-make and VS not dmc). Users will end
 up not using it.

 stb_image e.g. is in no "OS-Package" (which also don't exist for windows)
of course makefiles work, it's just hated by so many programmers... for windows there is 99% chance that already compiled executables/libraries exists.
Seems like I have ran into the 1% with all of the C projects I use.
Jan 13 2013
parent reply "evilrat" <evilrat666 gmail.com> writes:
On Sunday, 13 January 2013 at 10:47:41 UTC, David wrote:
 Seems like I have ran into the 1% with all of the C projects I 
 use.
cause my pc dead i'm now also forced to use glfw on osx(cause x11-d wrapper works on linux only), now i know why you are felt to that 1%, you are trying to use unstable versions of libs which is under middle of development process. unless dev team has fully automated snapshot building system you are out of luck to get precompiled binaries of actual version O_-
Jan 18 2013
parent reply David <d dav1d.de> writes:
Am 18.01.2013 09:13, schrieb evilrat:
 On Sunday, 13 January 2013 at 10:47:41 UTC, David wrote:
 Seems like I have ran into the 1% with all of the C projects I use.
cause my pc dead i'm now also forced to use glfw on osx(cause x11-d wrapper works on linux only), now i know why you are felt to that 1%, you are trying to use unstable versions of libs which is under middle of development process. unless dev team has fully automated snapshot building system you are out of luck to get precompiled binaries of actual version O_-
I compile pre-compile glfw for windows, but on Linux/OSX etc. I have it as submodule and it works fine! :)
Jan 19 2013
parent "evilrat" <evilrat666 gmail.com> writes:
On Saturday, 19 January 2013 at 15:32:46 UTC, David wrote:
 I compile pre-compile glfw for windows, but on Linux/OSX etc. I 
 have it
 as submodule and it works fine! :)
works for me too, but this is sad that i need to use 3rd party libs just to create render window and handling input(well, it's possible to create cocoa window using plain c, but that would require some time which i don't have right now) :(
Jan 20 2013
prev sibling next sibling parent David <d dav1d.de> writes:
 TODO:
  * documentation
  * other compilers (only a few lines for each compiler + a few to
 implement Linker functionality)
  * provide helpers for the taskpool (maybe)
  * add logging options, currently every command is printed to stdout
What I forgot was a config, I want to be able to do everything I have in main() in a config.
Jan 11 2013
prev sibling parent "Nicholas Londey" <londey gmail.com> writes:
As a relative newcomer to D I have been using to following build 
script. Not very sophisticated but has been enough so far.

module build;


import std.algorithm;
import std.array;
import std.conv;
import std.exception;
import std.file;
import std.path;
import std.process;
import std.range;
import std.regex;
import std.stdio;
import std.string;


enum D_SOURCE_RULE = ctRegex!`^[a-z][a-z0-9_]*\.d$`;
enum BUILD_COMMAND_ARGS_FILE = "build_command_args.txt";


void main(string[] args)
{
     enforce(args.length == 3, "Usage rdmd build.d <output bin> 
<source dir>");


     auto sourceFiles = map!(a => a.name)(dirEntries(args[2], 
SpanMode.depth));
     auto codeFiles = filter!(a => match(baseName(a), 
D_SOURCE_RULE))(sourceFiles);

     string[] options = ["-of" ~ args[1], "-od" ~ "obj", "-I.", 
"-J.", "-Dd" ~ "doc"];


     std.file.write(BUILD_COMMAND_ARGS_FILE, 
to!string(joiner(chain(options, codeFiles), "\n")));


     system(escapeShellCommand("dmd", " " ~ 
BUILD_COMMAND_ARGS_FILE));
}
Jan 11 2013