Closed winksaville closed 7 years ago
First attempt at a hello world example. It didn't work:
$ rm -rf build/
(venvpy3) wink@wink-desktop:~/prgs/test-craftr
$ ls -al
total 12
drwxr-xr-x 1 wink users 54 Nov 28 14:05 .
drwxr-xr-x 1 wink users 1624 Nov 28 11:03 ..
-rw-r--r-- 1 wink users 179 Nov 28 13:58 Craftrfile
-rw-r--r-- 1 wink users 62 Nov 28 13:59 hw.c
-rw-r--r-- 1 wink users 219 Nov 28 11:46 manifest.json
(venvpy3) wink@wink-desktop:~/prgs/test-craftr
$ cat manifest.json
{
"name": "hw",
"version": "1.0.0",
"dependencies": {
"lang.cxx": "*"
},
"options": {
"debug": {
"type": "bool"
},
"outbin": {
"type": "string",
"default": "main"
}
}
}
(venvpy3) wink@wink-desktop:~/prgs/test-craftr
$ cat Craftrfile
load_module('lang.cxx.*')
program = cxx_binary(
inputs = cpp_compile(
sources = ['hw.c'],
),
output = options.outbin
)
(venvpy3) wink@wink-desktop:~/prgs/test-craftr
$ craftr export
lang.cxx: loading "lang.cxx.clang" (with lang.cxx.clang.toolkit="")
lang.cxx: cxc.name="gcc"
lang.cxx: cxc.target_arch="x86_64-pc-linux-gnu"
lang.cxx: cxc.version="6.2.1"
(venvpy3) wink@wink-desktop:~/prgs/test-craftr
$ craftr build
ninja: error: '/home/wink/prgs/test-craftr/build/hw.c', needed by '/home/wink/prgs/test-craftr/build/hw-1.0.0/obj/*.o', missing and no known rule to make it
I then realized the problem was I needed to have the full path so I changed Craftrfile to set its sources to glob(['hw.c']) and it worked:
$ cat Craftrfile
load_module('lang.cxx.*')
program = cxx_binary(
inputs = cpp_compile(
sources = glob(['hw.c'])
),
output = options.outbin
)
But output is build/hw-1.0.0/main, I'd rather have it called hw
and put it in the root:
load_module('lang.cxx.*')
program = cxx_binary(
inputs = cpp_compile(
sources = glob(['hw.c']),
),
output = '/home/wink/prgs/test-craftr/hw'
)
I'd like to have the notion of "project root" directory something like this This might already exist and this probably isn't very "pythonic" but I think you get the idea:
load_module('lang.cxx.*')
def prj_root(srcs):
"""Take a parameter that is a string or a list of string
and appends the the project dir on to the front.
If the parameter is a single string it returns a single string
and if its a list it returns list of strings.
"""
import os
# getcwd() returns ./build/ to get its parent use dirname()
# Need a better way to gurantee we always get the 'project dir'
prj_dir = os.path.dirname(os.getcwd())
if isinstance(srcs, str):
ret_path = os.path.join(prj_dir, srcs)
return ret_path
elif isinstance(srcs, list):
ret_list = []
for src in srcs:
ret_list.append(os.path.join(prj_dir, src))
return ret_list
program = cxx_binary(
inputs = cpp_compile(
sources = prj_root(['hw.c']),
),
output = prj_root('hw')
)
Hey Wink,
it should have been load_module('lib.cxx.curlpp.*')
instead of lang.cxx...
, a typo. Anyway, I've simplified the example in the README to not load any dependencies and just compile some .cpp
files. I will need to implement #134 before cURL and cURLpp will compile on Linux and Mac OS. Also the pkg-config
loader is not yet implemented, otherwise YES it should just work with cURL installed globally with your package manager (see #131).
Regarding your second post: Craftr 2 behaves the same as Craftr 1 in that it changes to the build directory before any build scripts are executed. So any relative path you type and not explicitly convert to an absolute path is relative to the build directory, in this case hw.c
.
In Craftr 1 there was path.local()
which has been replaced by simply local()
so you write
program = cxx_binary(
inputs = cpp_compile(
sources = [local('hw.c')],
),
output = local('hw') # Only use local() if you want the output binary in your working tree
)
There's also the project_dir
builtin which points to the root of your project. There's some information on the Builtins Documentation but there still needs to be added a lot of documentation text. :)
Btw. you can use the following to create another target that runs your program.
run = gentarget([[program]], explicit=True)
Then use
$ craftr export
$ craftr build run
Thanks, local() is just fine and run worked OK, but its verbose for something that should be common. I suggest something like:
run = runtarget(program)
or
runtarget = program
How do I setup a clean
target?
Also, when I modify my Craftrfile and do a craftr export
followed immediately by a craftr build
ninja
reports there is nothing to do, this should be easier. In meson they automatically do the update of the build.ninja that would be a nice feature for the future.
I suggest deleting "Depending on the availability, the cURLpp library will be compiled from source or the flags will be retrieved with pkg-config (TODO). To build the project, use" from the example in README.md and adding the "runtarget" and then change craftr build
to craftr build run
or add craftr run
and then mention craftr build run
which will build and run in one step. (I assume command line options following run, craftr run a b c
, will be passed to main()
?)
Also mention where the executable is as ./build/hw-1.0.0/main isn't obvious.
I suggest deleting "Depending on the availability, the cURLpp library will be compiled from source or the flags will be retrieved with pkg-config (TODO). To build the project, use" from the example in README.md
Yes I forgot to remove it in the previous commit, the current example doesn't even use cURL anymore.
I suggest something like:
run = runtarget(program)
The gentarget()
thing is a workaround as I haven't thought of a good name yet. In Craftr 1 you used to import craftr.ext.rules
and use rules.run()
. I like runtarget()
though.
Thanks, local() is just fine and run worked OK, but its verbose for something that should be common.
You're right, it's rather common. However, that is the design I chose for Craftr from the very beginning. Every path is relative to the build tree by default, otherwise you need to use something to select exactly which path you want to use. If you want a path relative to your project directory, use local('path..')
or glob(['pattern1', 'pattern2', ...])
. Note that if you want to use local()
on multiple paths, there's a trick with map()
.
sources = map(local, ['foo.c', 'bar.c'])
How do I setup a clean target?
Currently not available, I am still thinking about the best way to add it. My current preference is to use a special clean command like craftr clean [target, [target, [...]]]
.
and then change craftr build to craftr build run or add craftr run and then mention craftr build run which will build and run in one step. (I assume command line options following run, craftr run a b c, will be passed to main()?)
craftr build
accepts zero or more target names on the command line, additional arguments will not be passed to main() but are instead also interpreted as targets to build. If you want to pass additional arguments, currently you need to add them to gentarget()
.
run = gentarget([[main, "foo", "bar"]], explicit=True)
Or with the runtarget()
I will add
run = runtarget(main, "foo", "bar")
Also mention where the executable is as ./build/hw-1.0.0/main isn't obvious.
You're right, it isn't obvious. That's how craftr organizes the build tree. I'll add this info.
Thanks for your input, Wink.
Thanks
After following the install instructions (I used pip to install py-nr and craftr from the checked our sources) I tried the example. My manifest.json is:
My Craftrfile is:
I then ran craftr export:
I checked an I do have curl installed on my system:
I think there needs to be something simpler, like a hello world example.