Coder Social home page Coder Social logo

bahmanm / bmakelib Goto Github PK

View Code? Open in Web Editor NEW
16.0 16.0 1.0 177 KB

A minimalist standard library for writing Makefiles.

Home Page: https://matrix.to/#/#.mk:matrix.org

License: Apache License 2.0

Makefile 36.54% Shell 63.06% Dockerfile 0.40%
bash gnumake make makefile shell-scripting

bmakelib's People

Contributors

bahmanm avatar nfultz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

nfultz

bmakelib's Issues

Wasteful `build` stage

It's quite wasteful to build the DEB & RPM packages on every push and simply discard them - esp since this Travis doesn't charge for FOSS repos.

A better strategy is to run build either only on tags or main.

Support enums/variants variable values

There are cases where all the possible values of a variable are already known in advance. For example, a variable deployment.environment can only be set to one of testing, staging and production.

It could be possible to capture that via a bmakelib target and validate the values.


For example, a pseudo-code could look like

$(call bmakelib.enum.define VAR,value1,value2)

...

a-target : $(call bmakelib.enum.get VAR)
	@echo VAR is $(VAR)
$ make VAR=value1 a-target
VAR is value1

$ make VAR=unknown a-target
Error:  invalid value for VAR: unknown

An alternative approach, which I'd prefer is using targets instead of call:

a-target : bmakelib.enum.define( MY_ENUM,value1,value2 )
a-target : bmakelib.enum.get( VAR,MY_ENUM )
	@echo VAR is $(VAR)

Cache build targets

Follow up on a conversation on Mastodon.

Is it possible to have a smarter™ way of caching a target based on the contents rather than modification time?

For example:

_expensive-target-workhorse:
	a bunch of expensive commands

expensive-target : _expensive-target-workhorse!cached

One idea for the implementation (non-PHONY targets) is to store the caches in PROJECT_ROOT/.bmakelib-caches & use checksums to identify if a target exists in the cache and retrieve the value. In the case of directories, the checksum of the tar'ed archive can be used.

Non-POSIX date format

This is a follow up on #37 which turned out to be invalid. Even though setting SHELL is good practice, it did not solve the failing tests on MacOS.

The problem was in the non-POSIX date format used in bmakelib.logged._make-and-log-target which only works on Linux.

Implement a fail fast $(shell)

Inspired by a thread in GNU Make mailing list.


One of the pains of using $(shell ...) is that you need to take extra measures to check the exit status of the command and potentially do something in case of failure.

It'd be great if there was something like bmakelib.shell.error-if-nonzero which, in case of failed shell commands, would immediately exit the makefile w/ an error message.

For example, given:

VAR1 := $(call bmakelib.shell.error-if-nonzero, echo kaboom && false)

...

Using the above makefile would result in

$ make 
*** Shell command "echo kaboom && false" with a non-zero return code.

Create the release via Travis

It should be possible to create the release and make the packages and upload them as part of the pipeline on tag event.

Review the documentation and improve the layout

Ideally each the doc for each feature, should start w/ a brief intro, at least one example (or synopsis) followed by functionalities/variables/targets.

Additionally, at this stage, the landing page is quite long and confusing. One possible improvement is moving the installation and usage sections to a "getting started" page to keep the landing page as lean as possible.

Unset `SHEL` in tests

Follow up on #36 which turned out to be invalid.

The culprit is not setting SHELL in the temporary Makefiles generated by tests. In its absence, Make will use /bin/sh which breaks tests on MacOS.

The `var` namespace

Move default-if-blank and error-if-blank to the new var namespace (eg bmakelib.var.default-if-blank)

Filenames and doc links should also be updated as it makes sense to either move them to a single var.mk file or prefix each existing file w/ var..

Package bmakelib as a Docker image

It can simplify using bmakelib, eg in a pipeline or a "toolbox" image on the user's machine.

For a decent coverage the following platforms should be supported:

  • Debian
  • openSUSE Leap (and Tumbleweed!)
  • RockyLinux

`default-if-blank` not working as expected w/ blank variable on the command line

Makefile

.PHONY : bmakelib/bmakelib.mk
include bmakelib/bmakelib.mk


.PHONY : a-target
a-target : bmakelib.default-if-blank( VAR1,foo )
a-target :
	@echo "VAR1 = '$(VAR1)'"

Expected

$ make VAR1= a-target
VAR1 = 'foo'

Actual

$ make VAR1= a-target
VAR1 = ''

Notes

$ make bmakelib.conf.default-if-blank.SILENT=no VAR1= a-target
Using default value 'foo' for variable 'VAR1'
VAR1 = ''

Generate high resolution timestamp

I find myself frequently needing to generate a µs precision timestamp.

some-target :
	@echo Microseconds:                $(call now,micros)
	@echo Milliseconds:                $(call now,millis)
	@echo Seconds:                     $(call now,secs)
	@echo Default precision (millis):  $(call now)
$ make some-target
Microseconds:                1693049901575259
Milliseconds:                1693049901575   
Seconds:                     1693049902  
Default precision (millis):  1693049901575   

This can be used to name log files or to prefix log entries w/ an accurate timestamp.

The question is, is it a common enough use-cases to be included in bmakelib?

See also

Provide a shorter namespace

Offer the user to use either bmakelib or other shorter namespace(s).

For example:

some-target : bmk.error-if-blank( VAR1 )

or (🝼 represents "Makemake" the god of fertility in Polynesian mythology)

some-target : 🝼.error-if-blank( VAR1 )

or even

some-target : 🕮.error-if-blank( VAR1 )
some-target : 🏗.error-if-blank( VAR1 )
some-target : 📚.error-if-blank( VAR1 )

See also #80

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

dockerfile
pkg/debbuild-env.Dockerfile
  • ubuntu 22.04
pkg/rpmbuild-env.Dockerfile

  • Check this box to trigger a request for Renovate to run again on this repository

Tests assume a system-dependent path to `make`

Discovered this when working on bmakelib Homebrew formula.

The test cases which test features that run make (such as !!bmakelib.logged), assume a system-dependent path to Gnu Make, ie make while that can change depending how make is invoked.

For example

\s*&& make -f .+ some-target

fails during Homebrew tests b/c Homebrew invokes make using its full path:

when_silent_is_no_and_echo_command_is_yes: Received:
    make[1]: Entering directory '/tmp/tmp.RWIV7iQv4E/test_logged'
    Logging target some-target to /tmp/tmp.RWIV7iQv4E/test_logged/some-target-20230819-11321692444771-396599475.logged
    exec 3>&1 4>&2 \
    && trap 'exec 2>&4 1>&3' 0 1 2 3 \
    && exec 1>/tmp/tmp.RWIV7iQv4E/test_logged/some-target-20230819-11321692444771-396599475.logged 2>&1 \
    && /home/linuxbrew/.linuxbrew/opt/make/bin/make -f Makefile some-target
    make[1]: Leaving directory '/tmp/tmp.RWIV7iQv4E/test_logged'
when_silent_is_no_and_echo_command_is_yes: Expected:
    make.+Entering.+
    Logging target some-target to .+
    exec .+ \
    \s*&& trap .+ \
    \s*&& exec .+ \
    \s*&& make -f .+ some-target
    make.+Leaving.+
test_logged: ERROR: when_silent_is_no_and_echo_command_is_yes failed.

NB: This bug does NOT impact bmakelib features but rather it's a flaw w/ how the tests are written.

Remove redundant `.PHONY` declarations

Almost all pattern rules in bmakelib are declared as .PHONY. That is redundant b/c by definition pattern rules will always be executed unless overridden.

Print the available targets and variables along w/ their docs

bmakelib should contain a target to list all available targets along w/ their documentation.

For example:

$ make bmakelib.help
TARGETS
-------
foo:  foo inline docs
bar:  bar inline docs
baz:  no documentation available

VARIABLES
---------
X:  no documentation available
Y:  Y inline docs

Installation using homebrew

The current targets only generate DEB and RPM packages which should be enough for most Linux distros.

Many programmers who use an Apple machine, use homebrew. Additionally homebrew is also available for Linux.

Use targets/variables w/o `bmakelib.` prefix

Currently all targets/variables are prefixed w/ bmakelib..
For example:

foo : bmakelib.error-if-blank(VAR1)
foo : 
	...

To reduce clutter and save some a few bytes, it should be possible to omit the prefix for all targets/variables if you ask for it; much in the same vein as bmakelib.conf.logged.convenience-target

For example:

bmakelib.conf.convenience-targets := yes
include bmakelib/bmakelib.mk

foo : error-if-blank(VAR1)
foo : 
	...

NB: To ensure backward compat and respect user's choice, this should be an opt-in, ie the default behaviour should be bmakelib.conf.convenience-targets := no.

Problem with bmakelib installation

I follow the steps and encounter problem in point 2.4: https://github.com/bahmanm/lemmy-synapse?tab=readme-ov-file#24-install-it-already
My terminal throws this
Makefile:30: bmakelib/bmakelib.mk: No such file or directory

when running this:

make \
    ansible.user=<REMOTE_USER> \
    ansible.password-auth=no \
    ansible.lemmy-synapse-server=<YOUR_INSTANCE> \
    install

Installing on ubuntu 22.04

What can be done? Hopebrew didnt throw any errors. The package is indeed installed, I can see it listed in brew installations.

Hard-coded path to bash

The variable SHELL has its value /bin/bash almost everywhere.

This works just fine on Linux but during attempts to create a homebrew formula, turned out that value loads the outdated bash 3 instead of the more recent 5.

The solution is to use /usr/bin/env bash instead.

Map/Dictionary in Makefiles

It would be useful to have a dictionary to group related variables/values, either statically or dynamically.

For example:

$(call dict.put,DEPLOY,env,prod)
$(call dict.put,DEPLOY,service,accounts)
$(call dict.put,DEPLOY,host,accounts.my-cool-product.com)
$(call dict.put,DEPLOY,gpg-key,992443840122)

$(call dict.put,BUILD,arch,x86_64)
$(call dict.put,BUILD,dir,/tmp/my-app/build)

It can, of course, be provided to work as a target:

define-config : dict.put( DEPLOY,env,prod )
define-config : dict.put( DEPLOY,service,accounts )
define-config : dict.put( DEPLOY,host,accounts.my-cool-product.com )
define-config : dict.put( DEPLOY,gpg-key,992443840122 )

deploy : define-config
deploy : 
	/usr/bin/deploy \
		--env $(call dict.get,DEPLOY,env) \
		--server $(call dict.get,DEPLOY,service) \
		$(call dict.get,DEPLOY,host)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.