After many years of using make, I've just started using jam (actually ftjam) for my projects.
In my project workspaces, I have two directories:
src where I build executables and libraries
test where my test programs are
I'm trying to set up a dependency on test programs so that each time I compile them, the libraries will be recompiled as well (if they need to).
Any suggestion on how to do it?
Ok this seems to be not an as easy question as I thought so I worked out a solution on my own. It uses a script to achieve the end result so I still hope that a Jam guru will have a jam-only solution.
Create a Jamrules in the root directory of the project with the common definitions.
Create a Jamfile in the root directory of the project with the following content:
SubDir . ;
SubInclude . src ;
SubInclude . test ;
Create a Jamfile in the src directory
SubDir .. src ;
Library mylib : mylib.c ;
Create a Jamfile in the test directory
SubDir .. test ;
Main mytest : mytest.c ;
Depends mytest : mylib$(SUFLIB) ;
With this setting, as long as I am in the root directory, whenever I try to build mytest the library will also be recompiled (if needed). I found an old message on the jammer mailing list describing it.
Alas this doesn't work if I'm in the test subdirectory since jam can only look down into subdirectories.
So, I created a simple script called jmk and put it together with the jam executable (so that both are in the path):
if [ "$JMKROOT" = "" ] ; then
JMKROOT=`pwd`
export JMKROOT
fi
cd $JMKROOT
jam $*
and I set the JMKROOT environment variable to the root of my project.
For when I compile in a Windows shell (that's why I want to use Jam) I simply use this small jmk.bat batch file:
#echo off
if "%JMKROOT%" EQU "" set JMKROOT=%CD%
set OLDCD=%CD%
cd %JMKROOT%
jam %1 %2 %3 %4 %5 %6 %7 %8 %9
cd %OLDCD%
I'm using Jam in one of my projects, and I am encountering your very situation. I have my executable programs in the bin subdirectory, and my static libraries are kept in the lib subdirectory.
In my top-level Jamfile, I type in SubDir TOP ;. This initializes the $(TOP) variable to point to the directory containing this Jamfile. I then add lines such as SubInclude TOP bin llvm-tblgen and SubInclude TOP lib Support, which adds the contents of the Jamfiles in bin/llvm-tblgen and lib/Support to the build.
In the Jamfile in bin/llvm-tblgen, I type in SubDir TOP bin llvm-tblgen ;. I do the same in the Jamfile in lib/Support, but I use SubDir TOP lib Support ; instead. The key when entering SubDir rules is to type in the names of each subdirectory from the TOP to the directory containing this Jamfile.
Then, when it is time to set the linkline of my executable target, I reference the support library like this: $(TOP)/lib/Support/libLLVMSupport.a. Jam expands this path into the location of libLLVMSupport.a, relative to where I run Jam, even if I cd into the bin/llvm-tblgen directory and run Jam manually from there.
This makes it very easy to manage large projects that contain cross-directory dependencies. This solution, unlike your earlier one, lets you run Jam directly. Hope it helps you!
Related
I have written a library in OCaml with all of its sources located in lib folder.
I also prepared "facade" executables in bin folder.
Now I would like to prepare some examples how to use the above mentioned executables.
To do this I need to either copy an executable beforehand or (preferably) tell Dune to use a newly created one after build.
And here is my question.
Dune's copy_files stanza does not allow1 me to copy from _build folder.
Is there any other way to use fresh executables each time after building or do I need to copy them at some point and keep up to date?
Below is the structure of the project (in case verbal description was misleading in any way).
root
lib <- source
bin <- frontend for source
examples <- how to use the above frontend
1 By not allow I mean the following usage of this stanza:
( copy_files %{project_root}/_build/default/bin/program.exe )
A solution, as suggested by #Lhooq, might be to use dune exec command with --root parameter.
In regard to the provided scenario, if we make a script:
dune exec --root=../.. ./bin/some_program.exe
(*
Where 'some_program' is the name of an .ml file located in bin folder.
I assumed here that the program is compiled to native code, not to bytecode (hence the .exe).
*)
and place it in examples directory, then by invoking it we will actually run the latest build of the program defined in some_program.ml located in bin folder.
And just to make things clear: bin folder does NOT contain any compiled files (neither .exe nor .bc) .
There is some CMake magic I don't understand. How should a CMakeLists.txt file look like for a small C++ project with directories like this:
.
├── bin
└── src
├── src
└── test
bin — directory for built program
src/src — directory for source
src/test — directory for tests
The tests will need to include files from src/src.
I'd like to manage all the operations from cmake, however at this moment I even can't cause cmake to compile file in src/c.cpp.
Any help, links are welcome.
Your CMake files should reside in the main source directory and its sub-directories. The easiest approach is to have one CMakeLists.txt in the src directory, which includes all files from src/src and src/test. A very minimalistic example could look like the following:
# CMakeLists.txt in src
project(myExample)
set(myExample_SOURCES
src/file1.cpp
src/main.cpp)
add_executable(myExecutable ${myExample_SOURCES})
set(myExample_test_SOURCES
src/file1.cpp
test/test_file2.cpp
test/test_main.cpp)
add_executable(myTestSuite ${myExample_test_SOURCES})
The output directory is normally not specified, because you can have different active
builds in parallel with
different options, e.g. you can have one build in debug mode -O0 -g, another one in release mode with -O2 -g flags and a third one in release mode with heavy optimization flags -O3. Every build resides in its own directory (e.g. build-debug, build-rel,
build-opt).
You should create the output directory (bin in your case) manually and call the cmake command inside this directory. As an argument you have to supply the path to the main CMakeLists.txt. In other words, just execute
cmake ../src
when you are inside bin. This will take all files from the src directory and put the output to the bin directory.
You can easily create a second output directory, say bin2, where you specify different build flags. The ccmake provides a very minimalistic GUI for that.
This helped me to start with cmake examples.html
I wrote a C++ program (with a main.cpp, and various header and implementation files) that compiles fine under g++. Now I am trying to compile it in Cern's ROOT library, but I do not know how to, since the only way I know how to compile files in ROOT is by using .L main.cpp.
How can I include multiple files in ROOT?
The most reliable way to use ROOT (at least historically and currently) is to ignore the interpreter other than for the simplest explorations and explicitly compile your C++ programs against the ROOT libraries. For example, use
g++ MySource.cc `root-config --libs --cflags` -o foo
to compile an executable "foo" from a single source file. For more info on that helper script run "root-config --help".
Multi-file programs/libraries are nothing special provided that you supply the required args to point at the ROOT libraries and headers (and that the libs are available in LD_LIBRARY_PATH at runtime.) Standard C++ guides will explain that step if needed. You can safely put this into a makefile, too.
For my money this is both easier and more reliable than using the .L etc. commands in the CINT interpreter. Last time I tried, ACLiC was actually compiling against a temporary (and mangled) version of the specified source file, so any error messages from the compiler were pretty much useless!
I use CMake to compile my ROOT-based projects.
If you have a project directory proj/ and it contains src/ and bin/, you'll need 3 CMakeList.txt files, one in each directory.
A simple example CMakeList.txt in the main project directory:
cmake_minimum_required(VERSION 2.6)
project (SOME_PROJ_NAME)
add_subdirectory(src)
add_subdirectory(bin)
src/ directory is where you keep your .h and .cxx proj. library files. Example CMakeList.txt file:
# get all the *.cxx filenames, to compile them into a lib
file(GLOB SOME_PROJ_LIB_SRCS "${PROJECT_SOURCE_DIR}/src/*.cxx")
# include ROOT library and include files
include_directories(/path/to/root/dir/include/dir)
link_directories(/path/to/root/dir/lib/dir)
# and compile src into a library
add_library(Proj_lib_name ${SOME_PROJ_LIB_SRCS})
# here, list the ROOT libraries you require
target_link_libraries(Proj_lib_name dl Core Cint RIO Net Hist Graf Graf3d Gpad Tree Rint Postscript Matrix Physics MathCore Thread Gui pthread m)
bin/ directory is where you keep your app .cxx files and it has a CMakeList.txt file:
include_directories(${PROJECT_SOURCE_DIR}/src)
link_directories(${PROJECT_SOURCE_DIR}/src)
include_directories(/path/to/root/dir/include/dir)
link_directories(/path/to/root/dir/lib/dir)
add_executable(example_app.exe example_app.cxx)
target_link_libraries(example_app.exe Proj_lib_name dl Core Cint RIO Net Hist Graf Graf3d Gpad Tree Rint Postscript Matrix Physics MathCore Thread Gui pthread m)
Finally, to compile ROOT-based code with CMake, out of source, you create a "build" dir in your top level project dir, so that your dir structure looks like this:
proj/
bin/
build/
src/
Then
cd build
cmake ..
Your binaries will be located in build/bin/ directory
Hope this helps.
It appears that I would simply .L <filename> for each file I want, since .L tells ROOT to "load the contents of file in memory." Though now I am not too sure which order to load the files in, as they are giving me errors.
How do I tell cmake where it should output its build data?
Let's say I have a dir with the source code called src/,
and then since cmake outputs a lot of files I would like him to put all of that in
a dir called build/.
BUT I would like him to put the generated Makefile in the project root,
so I don't have to go into the build dir to build the application.
Is this possible with cmake?
I have managed to get the cmake out put if I fun cmake in the build dir like this:
cd build/
cmake ../src/
make
./hello
But it would be nice to stay in the project root and type something like this
cmake
make
./hello
I guess that I need to put a CMakeList.txt in the project root with some magic commands telling him where he could put the object files and where he can find the source code.
Thanks
Update:
Since my question is a little bit vague.
After I have run the cmake commands this is how I would like my tree to look like:
src/CMakeLists.txt
src/hello.c
src/hello.h
build/CMakeCache.txt
build/CMakeFiles/
build/cmake_install.cmake
CMakeLists.txt
Makefile
So the question is how should the CMakeLists.txt look like in this setup.
CMakeLists.txt
src/CMakeLists.txt
But maybe that is not possible?
BUT I would like him to put the generated Makefile in the project root, so I don't have to go into the build
dir to build the application.
cmake not designed for that, as I know,
BUT you can stay in the project root and type:
make -C build
./hello
with custom build rules or set_target_properties,
you can force cmake to put result executable to
sources directory or you can use
./build/hello
Type "cd build && cmake .." you need only once,
after that make will automaticaly start cmake, if something
changed.
cmake wants you to have a fresh build directory.
Okay, i get what you want. I think, you can achieve this with some machinery in CMakeLists.txt. Of course, it's not option if you are not project developer.
In root CMakeLists.txt you can add file(WRITE ...) command, which would write Makefile into ${CMAKE_SOURCE_DIR}. This Makefile would contain these commands for every target:
<target>:
cd ${CMAKE_BUILD_DIR} && ${CMAKE_MAKE_PROGRAM} <target>
So, now you can run make from source dir and it will build your project in build dir.
Simply use
cmake .
make
in your src directory. The (.) dot on unix systems addresses the current directory. Keep in mind doing so is actually not recommended since there will be a lot of build files in your src directory you'll have to clean up afterwards or at release time.
I'd like to switch to using Jam as my build system. Currently, I have a src, include and build directories and I'm wondering how I can get Jam to put object files in the build directory and search for include files in the include directory.
Good for you for using Jam! I think you'll find it a lot easier than makefiles, once you get past a few of its oddities.
What you are asking about is a setup I have often used. At the top level, I have three directories: src, inc, and build. There is also a file called Jamfile:
# top-level Jamfile
SubDir . ;
SubInclude src ;
SubInclude build ;
The SubDir line establishes the location of this file within the directory structure, and seems to be necessary for Jam to work. (I think Jam could have been designed to not need it, but there it is, so be it.) The SubInclude lines tell Jam to include two subdirectories. The inc subdirectory is not included because there is nothing there that needs to be compiled directly; all its contents will be included by other files.
Within inc, I have a header file called header.h:
/* header.h */
#define MESSAGE "Hello world!"
Within src, I have the source of the main program, main.c:
/* main.c */
#include "header.h"
#include <stdio.h>
int main(int argc, char** argv)
{
printf("%s\n", MESSAGE);
return 0;
}
Also within src is another Jamfile with these contents:
# src/Jamfile
SubDir .. src ;
HDRS += ../inc ;
Library helloworld : main.c ;
The SubDir line locates the Jamfile within the directory structure. The HDRS line tells Jam where additional headers can be found (it will pass this on to the compiler when the time comes). Note the use of the += operator, which appends to an existing variable. The Library line tells Jam to build a library out of main.c (yes, a library with a main() is a little weird, but OK on a small project like this).
Within build is a single Jamfile:
# build/Jamfile
SubDir .. build ;
Main helloworld ;
LinkLibraries helloworld : helloworld ;
SubInclude .. src ;
The SubDir line locates the Jamfile within the directory structure. The Main line tells Jam to build an executable called helloworld. Note that it has no source file dependencies. If it did, it would look like Main hello world : foo.c ;. The LinkLibraries line tells Jam to link the helloworld executable with a library, also called helloworld. It is OK in this case that the executable and library have the same name, but in a real program you might want to give them different (and better) names. The SubInclude line tells Jam to look in the src directory for more code to build. This is how the dependency between the executable and the library gets resolved. It is important that this line come last.
Now, if you navigate to the build directory and execute the jam command, Jam will build a helloworld.a file in src, and link it into a helloworld executable in build.
Because all the code in src is being compiled into a library, there are no .o files left over. They are all stored inside the .a file, which is an archive, after all. If you have additional source files in build (like the hypothetical foo.c mentioned above), then you would have .o files left over in the build directory after compiling.
Good luck with all this. I learned most of what I know about Jam from the Perforce website and through experimentation. The main Perforce page for Jam is here.